package com.gitee.wsl.common.chart.sample.arc

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import com.gitee.wsl.android.ext.math.calcArcEndPointXY
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.chart.adapter.DataSource
import com.gitee.wsl.common.chart.adapter.SelectItemChartAdapter
import com.gitee.wsl.common.chart.model.PlotDot
import com.gitee.wsl.common.chart.render.foreground.info.PlotLegendItem
import com.gitee.wsl.common.chart.render.foreground.info.PlotAttrInfoRender
import com.gitee.wsl.common.chart.sample.XChart
import com.gitee.wsl.common.chart.sample.arc.adapter.ArcLineChartAdapter
import com.gitee.wsl.common.chart.sample.arc.model.ArcLineData
import com.gitee.wsl.common.ui.draw.type.DotStyle
import com.gitee.wsl.common.ui.draw.type.HorizontalAlign
import com.gitee.wsl.common.ui.draw.type.PanMode
import com.gitee.wsl.common.ui.draw.type.VerticalAlign
import com.gitee.wsl.android.ui.ext.type.drawPercentArc
import com.gitee.wsl.android.ui.ext.type.textHeight
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.div
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.sub


import timber.log.Timber


class ArcLineChart(val adapter: ArcLineChartAdapter = ArcLineChartAdapter()) : XChart(adapter),
    SelectItemChartAdapter<ArcLineData> by adapter{

    //开放标签和线画笔让用户设置
    val labelPaint: Paint by lazy {
        Paint().apply {
            color = Color.BLACK
            textSize = 18f
            isAntiAlias = true
            textAlign = Paint.Align.RIGHT
        }
    }

    val linePaint: Paint by lazy {
        Paint().apply {
            color = Color.rgb(180, 205, 230)
            isAntiAlias = true
            strokeWidth = 3f
            style = Paint.Style.FILL
        }
    }

    //数据源
    var dataSet by DataSource(adapter)


    //柱形间距所占比例
    var barInnerMargin = 0.5f

    //标签偏移
    var labelOffsetX = 0.0f

    //内环填充颜色
    val fillPaint: Paint by lazy {
         Paint().apply {
             isAntiAlias = true
             color = Color.BLACK
         }
    }

    //半径
    override var radius = 0.0f

    //内环半径	
    var innerRaius = 0.6f

    //附加信息类
    var plotAttrInfo: PlotAttrInfoRender = PlotAttrInfoRender()
    
    init {
        plotLegend.legendType=ChartEnum.LegendType.ROW
        plotLegend.horizontalAlign= HorizontalAlign.CENTER
        plotLegend.verticalAlign= VerticalAlign.BOTTOM
        plotLegend.isShowBox = true
        plotLegend.isShowBackground=false
    }


    override fun getType(): ChartEnum.ChartType {
        return ChartEnum.ChartType.ARCLINE
    }

    override fun calcPlotRange() {
        super.calcPlotRange()
        radius = (bodyViewport.width/ 2f).coerceAtMost((bodyViewport.height/ 2f))
    }
    
    /**
     * 设置柱形间空白所占的百分比
     * @param percentage 百分比
     */
    fun setBarInnerMargin(percentage: Float): Boolean {
        if (percentage.compareTo(0.0f) == -1) {
            Timber.d("此比例不能为负数噢!")
            return false
        }
        if (percentage.compareTo(0.9f) == 1 || percentage.compareTo(0.9f) == 0
        ) {
            Timber.d("此比例不能大于等于0.9,要给柱形留下点显示空间!")
            return false
        } else {
            barInnerMargin = percentage
        }
        return true
    }

    /**
     * 检查角度的合法性
     * @param Angle 角度
     * @return 是否正常
     */
    protected fun validateAngle(Angle: Float): Boolean {
        if (Angle.compareTo(0.0f) == 0 || Angle.compareTo(0.0f) == -1) {
            Timber.d("扇区圆心角小于等于0度. 当前圆心角为:$Angle" )
            return false
        }
        return true
    }


    private fun renderCap(
        canvas: Canvas,
        radius: Float,
        arrCapPoint: List<PointF>,
        arrCapColor: IntArray
    ): Boolean {
        linePaint.color = Color.RED
        for (i in arrCapPoint.indices) {
            linePaint.color = arrCapColor[i]
            canvas.drawCircle(
                arrCapPoint[i].x, arrCapPoint[i].y,
                radius, linePaint
            )
        }
        return true
    }


    private fun renderLabels(canvas: Canvas, radius: Float, arrPoint: List<PointF>): Boolean {
        var i = 0
        var currentAngle = 0.0f
        val txtHeight = (labelPaint.textHeight) / 3
        for (cData in dataSet) {
            currentAngle = cData.sliceAngle
            if (!validateAngle(currentAngle)) continue
            labelPaint.color = cData.color

            //标识
            canvas.drawText(
                cData.label, arrPoint[i].x - labelOffsetX,
                arrPoint[i].y + txtHeight, labelPaint
            )
            i++
        }
        return true
    }


    private fun drawPlot(canvas: Canvas): Boolean {
       
        //中心点坐标
        val cirX: Float = bodyViewport.centerX
        val cirY: Float = bodyViewport.centerY
        var radius: Float = radius
        try {
            //用于存放当前百分比的圆心角度
            var currentAngle = 0.0f
            val offsetAngle = OFFSET_ANGLE
            var i = 0
            val dataCount = dataSet.size
            val barTotalSize: Float = Math.sub(radius, Math.mul(radius, innerRaius))
            val mulBarSize = Math.div(barTotalSize, dataCount.toFloat())
            val spaceSize: Float = Math.mul(mulBarSize, barInnerMargin)
            val barSize: Float = Math.sub(mulBarSize, spaceSize)

            //标签
            var labelRadius = 0.0f
            val arrLabPoint = mutableListOf<PointF>()

            //箭头
            val arrCapPoint = mutableListOf<PointF>()
            val arrCapColor = IntArray(dataCount)


            //绘制底盘
            canvas.drawCircle(cirX, cirY, radius, fillPaint)

            //绘制柱形
            for (cData in dataSet) {
                currentAngle = cData.sliceAngle
                if (!validateAngle(currentAngle)) continue
                linePaint.color = cData.color
                canvas.drawPercentArc(linePaint, cirX, cirY, radius, offsetAngle, currentAngle, true)

                //箭头
                var point = Math.calcArcEndPointXY(
                    cirX, cirY,
                    radius - barSize / 2,
                    Math.add(offsetAngle, currentAngle)
                )
                arrCapPoint.add(PointF(point.x, point.y))
                arrCapColor[i] = cData.color

                //标签
                labelRadius = radius - barSize / 2
                point = Math.calcArcEndPointXY(
                    cirX, cirY,
                    labelRadius,
                    Math.add(offsetAngle, 0f)
                )
                arrLabPoint.add(PointF(point.x, point.y))

                //底
                canvas.drawCircle(cirX, cirY, radius - barSize, fillPaint)
                radius = Math.sub(radius, mulBarSize)
                i++
            }
            renderCap(canvas, barSize * 0.8f, arrCapPoint, arrCapColor)

            //绘制Label		
            renderLabels(canvas, radius, arrLabPoint)

            //图KEY
            //plotLegend.renderRoundBarKey(canvas, mDataset)
            //renderLegend(canvas, mDataset)

        } catch (e: Exception) {
            Timber.d( "error:$e")
            return false
        }
        return true
    }

    /*fun renderLegend(canvas: Canvas,dataSet:List<ArcLineData>){
        var key = ""
        val legendList= mutableListOf<LegendItem>()
        for (cData in dataSet) {

            key = cData.mKey

            if (key.isEmpty()) continue

            val dot = PlotDot()
            dot.dotStyle = DrawEnum.DotStyle.RECT

            legendList.add(LegendItem(key,cData.mColor,dot))
        }

        plotLegend.renderInfo(canvas,legendList)
    }*/

    override fun createLegendData(): List<PlotLegendItem> {
        var key = ""
        val legendList= mutableListOf<PlotLegendItem>()
        for (cData in dataSet) {

            key = cData.key

            if (key.isEmpty()) continue

            val dot = PlotDot()
            dot.dotStyle = DotStyle.RECT

            legendList.add(PlotLegendItem(key,cData.color,dot))
        }
        return legendList
    }

    override fun renderBody(canvas: Canvas): Boolean {
            super.renderBody(canvas)
            calcPlotRange()
            //绘制图表
            if (drawPlot(canvas)) {
                //绘制附加信息
                plotAttrInfo.renderAttrInfo(canvas, bodyViewport.centerX, bodyViewport.centerY, this.radius)
                //绘制标题
                drawTitle(canvas)
            } else {
                return false
            }
       return true
    }

    
    override fun render(canvas: Canvas) {
            if (isScrollEnabled) {
                canvas.save()
                when (plotPanMode) {
                    PanMode.HORIZONTAL -> canvas.translate(translateXY[0], 0f)
                    PanMode.VERTICAL -> canvas.translate(0f, translateXY[1])
                    else -> canvas.translate(translateXY[0], translateXY[1])
                }

                //绘制图表
                super.render(canvas)

                //还原								
                canvas.restore()
            } else {
                //绘制图表
                super.render(canvas)
            }

    }



    companion object{

        //初始偏移角度
         const val OFFSET_ANGLE = 270f
    }
}